/*
	Visp is an opensource visual performance application built with Adobe® AIR™.
	Copyright (C) 2007 Mike Creighton
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
	
	Mike Creighton can be found at http://www.mikecreighton.com		
*/
package
{
	import com.visp.events.RangeEvent;
	import com.visp.events.DisplayMouseEvent;
	import com.visp.events.BangEvent;
	import com.visp.render.IRenderable;
	import flash.display.Sprite;
	import flash.display.Shape;
	import com.visp.constants.OutputSize;
	import flash.geom.ColorTransform;
	import com.visp.constants.RendererBang;
	import com.visp.constants.RendererRange;
	import flash.events.Event;

	/**
	 * The BasicRenderer class is a demonstration of visp's input capabilities
	 * and how to incorporate these capabilities into your own custom renderers.
	 * 
	 * This demo uses a basic rectangle as the subject of manipulation. Using
	 * the various input events, we'll do the following:
	 * 
	 *    - Range1 : Adjust its rotation speed.
	 *    - Range2 : Adjust its scale.
	 *    - Range3 : Adjust its alpha.
	 *    - Bang1 : Randomly change its color.
	 *    - Bang2 :  Randomly change its position.
	 */
	public class BasicRenderer extends Sprite implements IRenderable
	{
		private var _ground : Shape;
		private var _subject : Shape;
		private var _rotationSpeed : Number;
		private var _maxScale : Number; // This is the maximum scale multiplier for our subject
		private var _maxRotation : Number; // This is the maximum rotation speed in degrees
		
		public function BasicRenderer()
		{
			super();
			
			// Drop a grey background.
			this._ground = new Shape();
			this._ground.graphics.beginFill(0x888888, 1);
			// Using com.visp.constants.OutputSize to discover the area we can work within.
			this._ground.graphics.drawRect(0, 0, OutputSize.WIDTH, OutputSize.HEIGHT);
			this._ground.graphics.endFill();
			this.addChild(this._ground);
			
			this._subject = new Shape();
			this._subject.graphics.beginFill(0x000000, 1);
			this._subject.graphics.drawRect(-25, -25, 50, 50);
			this._subject.graphics.endFill();
			this._subject.x = OutputSize.WIDTH / 2;
			this._subject.y = OutputSize.HEIGHT / 2;
			this.addChild(this._subject);
			
			this._maxRotation = 5;
			this._rotationSpeed = 0;
			this._maxScale = 10;
		}
		
		public function start():void
		{
			// Subscribe to the enterframe event so that we can be continually
			// updating the rotation of our subject.
			this.addEventListener(Event.ENTER_FRAME, this._handleEnterFrame);
		}
		
		/**
		 * The halt() method is not implemented in visp v1.0.0
		 */
		public function halt():void { }
		
		public function handleBangOn(e:BangEvent):void
		{
			switch(e.id) {
				// Randomly change the color of the subject shape
				case RendererBang.ID_0:
					this._applyNewColor();
				break;
				
				// Randomly change the position of the subject shape
				case RendererBang.ID_1:
					this._findNewPosition();
				break;
			}
		}
		
		public function handleBangOff(e:BangEvent):void
		{
		}
		
		public function handleRange(e:RangeEvent):void
		{
			switch(e.id) {
				// Adjust the alpha of the subject
				case RendererRange.ID_0:
					this._subject.alpha = e.value;
				break;
				
				// Adjust the scale of the subject
				case RendererRange.ID_1:
					this._subject.scaleX = this._subject.scaleY = e.value * this._maxScale;
				break;
				
				// Adjust the current rate of rotation for the subject
				case RendererRange.ID_2:
					this._rotationSpeed = e.value * this._maxRotation;
				break;
			}
		}
		
		public function handleMouseEvent(e:DisplayMouseEvent):void
		{
			if(e.type == DisplayMouseEvent.DOWN || e.type == DisplayMouseEvent.DOWN_MOVE) {
				this._subject.x = e.position.x;
				this._subject.y = e.position.y;
			}
		}
		
		public function destroy():void
		{
			// Clean up the callback to the ENTER_FRAME event
			this.removeEventListener(Event.ENTER_FRAME, this._handleEnterFrame);
		}
		
		// ---------------------------------------------------------
		// Begin Custom Functions
		// ---------------------------------------------------------
		
		private static function _getRandomInt(maxValue : int) : int {
			return Math.round(Math.random() * maxValue);
		}
		
		/**
		 * Applies a random RGB value to the _subject rectangle
		 */
		private function _applyNewColor() : void 
		{
			var r : uint = BasicRenderer._getRandomInt(255);
			var g : uint = BasicRenderer._getRandomInt(255);
			var b : uint = BasicRenderer._getRandomInt(255);
			var color : ColorTransform = new ColorTransform(1, 1, 1, this._subject.alpha, r, g, b, 0);
			this._subject.transform.colorTransform = color;
		}
		
		/**
		 * Moves the _subject rectangle to a new random position
		 * within the canvas area.
		 */
		private function _findNewPosition() : void
		{
			this._subject.x = BasicRenderer._getRandomInt(OutputSize.WIDTH);
			this._subject.y = BasicRenderer._getRandomInt(OutputSize.HEIGHT);
		}
		
		/**
		 * EnterFrame callback handler that we'll use for updating the 
		 * rotation value of the _subject rectangle. This gives us the
		 * ability to animate.
		 */
		private function _handleEnterFrame(event : Event) : void
		{
			this._subject.rotation += this._rotationSpeed;
		}
		
	}
}